package tsing.javase.thread.utils;

import java.lang.reflect.Method;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 *
    CountDownLatch适用于在多线程的场景中需要等待所有子线程全部执行完毕之后再做操作的场景。
    原理：
         初始化一个CountDownLatch实例传参2，因为我们有2个子线程，每次子线程执行完毕之后调用countDown()方法给计数器-1，主线程调用await()方法后会被阻塞，直到最后计数器变为0，await()方法返回，执行完毕。
         他和join有个区别，像我们这里用的是ExecutorService创建线程池，是没法使用join的，相比起来，CountDownLatch的使用会显得更加灵活。
         CountDownLatch基于AQS实现，用volatile修饰state变量维持倒数状态，多线程共享变量可见。
         CountDownLatch通过构造函数初始化传入参数实际为AQS的state变量赋值，维持计数器倒数状态
         当主线程调用await()方法时，当前线程会被阻塞，当state不为0时进入AQS阻塞队列等待。
         其他线程调用countDown()时，通过CAS修改state值-1，当state值为0的时候，唤醒所有调用await()方法阻塞的线程
 */

public class CountDownLatchTest {
    public static void main(String[] args) throws Exception{
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        CountDownLatch countDownLatch = new CountDownLatch(2);

        Class<? extends CountDownLatch> aClass = countDownLatch.getClass();


        executorService.submit(()->{
            try {
                Thread.sleep(1000);
                System.out.println("写excelA完成");
                countDownLatch.countDown();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });

        executorService.submit(()->{
            try {
                Thread.sleep(3000);
                System.out.println("写excelB完成");
                countDownLatch.countDown();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });

        System.out.println("等待excel写入完成");
        countDownLatch.await();
        System.out.println("开始打包发送数据..");

        executorService.shutdown();

    }
}

